﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Diagnostics;
using System.Windows.Forms;

namespace AutoF3
{
    public class SheetBuilder
    {
        public List<Problem> problemList = new List<Problem>();
        public List<FinalizedProblem> finalizedProblemList = new List<FinalizedProblem>();
        public List<string> problemNameList = new List<string>();

        public int Count;

        public SheetBuilder() { Count = 0; }

        //should take arguements of filenames
        public void BuildSheet(string name, string number, string intro, string problemSheetFilepath, string solutionSheetFilepath) 
        {
            string fileName = GetFileNameFromFilePath(problemSheetFilepath);
            string directory = GetDirectoryFromFilePath(problemSheetFilepath);

            if (File.Exists(problemSheetFilepath)) 
                File.Delete(problemSheetFilepath);
            File.WriteAllText(problemSheetFilepath, GenerateProblemSheetSource(name, number, intro));

            bool success = CompileIntoPDF(fileName, directory);

            string fileNameWithoutExtension = fileName.Substring(0, fileName.Length - 4);
            if (File.Exists(directory + fileNameWithoutExtension + ".txt"))
                File.Delete(directory + fileNameWithoutExtension + ".txt");
            if (File.Exists(directory + fileNameWithoutExtension + ".aux"))
                File.Delete(directory + fileNameWithoutExtension + ".aux");

            if (solutionSheetFilepath != null)
            {
                if (File.Exists(solutionSheetFilepath)) 
                    File.Delete(solutionSheetFilepath);
                File.WriteAllText(solutionSheetFilepath, GenerateSolutionSheetSource(number));

                if (success) //don't want to throw another error if pdflatex isn't installed
                    success = CompileIntoPDF(GetFileNameFromFilePath(solutionSheetFilepath), GetDirectoryFromFilePath(solutionSheetFilepath));
            }
        }

        private bool CompileIntoPDF(string fileName, string directory)
        {
            try
            {
                Process proc = new Process();
                proc.StartInfo.FileName = "pdflatex";
                proc.StartInfo.Arguments = fileName;
                proc.StartInfo.WorkingDirectory = directory;
                proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
                proc.Start();
                proc.WaitForExit();

                return true;
            }
            catch (Exception e) 
            {
                MessageBox.Show("This computer does not have pdflatex installed. The raw TeX file(s) were written but no PDF file was produced", "Error");
                return false;
            }
        }

        private string GetFileNameFromFilePath(string filepath) 
        {
            int index = filepath.LastIndexOf("\\");
            return filepath.Substring(index + 1);
        }

        private string GetDirectoryFromFilePath(string filepath)
        {
            int index = filepath.LastIndexOf("\\");
            return filepath.Substring(0, index) + "\\";
        }

        private string GenerateProblemSheetSource(string name, string number, string intro)
        {
            StringBuilder build = new StringBuilder();
            build.Append(@"%This is a Comment" + "\r\n"
                + @"%Can change the following to 11pt to make more stuff fit on a page." + "\r\n"
                + @"\documentclass[11pt, oneside, letterpaper]{article}" + "\r\n"
                + @"\usepackage{amsmath}" + "\r\n"
                + @"\usepackage{amssymb}" + "\r\n"
                + @"\usepackage{amsthm}" + "\r\n"
                + @"\usepackage[pdftex]{graphicx}" + "\r\n"
                + @"\title{F$^3$-6.32 b}" + "\r\n"
                + @"\date{}" + "\r\n"
                + @"\setlength{\parindent}{0pt}" + "\r\n"
                + @"\pagestyle{empty}" + "\r\n"
                + @"\voffset = -0.5in" + "\r\n"
                + @"\headheight 0in %this moves the whole title up." + "\r\n"
                + @"\headsep 0in  %moves up more..." + "\r\n"
                + @"\textheight = 720pt" + "\r\n"
                + @"%The Following can change the margins, but I'm not sure how.  I think cm can also be used?  Play with them." + "\r\n"
                + @"\textwidth = 470pt" + "\r\n"
                + @"%\marginparwidth = 15pt" + "\r\n"
                + @"\oddsidemargin = 0pt" + "\r\n"
                + @"\pagestyle{empty}" + "\r\n"
                + @"\begin{document}" + "\r\n"
                + @"\begin{center}{\LARGE $F^3-" + number + @"$}\end{center}" + "\r\n"
                + @"%This is the intro." + "\r\n"
                + @"\textsl{" + intro + " -- " + name + "}" + "\r\n\r\n"
                + @"%insert the probs after each \item" + "\r\n"
                + @"\begin{enumerate}" + "\r\n\r\n");

            foreach (var finalizedProblem in finalizedProblemList)
                build.Append(@"\item " + finalizedProblem.problemText + "\r\n\r\n");

            build.Append(@"\end{enumerate}" + "\r\n"
                + @"\end{document}");

            return build.ToString();
        }

        private string GenerateSolutionSheetSource(string number)
        {
             StringBuilder build = new StringBuilder();
            build.Append(@"%This is a Comment" + "\r\n"
                + @"%Can change the following to 11pt to make more stuff fit on a page." + "\r\n"
                + @"\documentclass[11pt, oneside, letterpaper]{article}" + "\r\n"
                + @"\usepackage{amsmath}" + "\r\n"
                + @"\usepackage{amssymb}" + "\r\n"
                + @"\usepackage{amsthm}" + "\r\n"
                + @"\usepackage[pdftex]{graphicx}" + "\r\n"
                + @"\title{F$^3$-6.32 b}" + "\r\n"
                + @"\date{}" + "\r\n"
                + @"\setlength{\parindent}{0pt}" + "\r\n"
                + @"\pagestyle{empty}" + "\r\n"
                + @"\voffset = -0.5in" + "\r\n"
                + @"\headheight 0in %this moves the whole title up." + "\r\n"
                + @"\headsep 0in  %moves up more..." + "\r\n"
                + @"\textheight = 720pt" + "\r\n"
                + @"%The Following can change the margins, but I'm not sure how.  I think cm can also be used?  Play with them." + "\r\n"
                + @"\textwidth = 470pt" + "\r\n"
                + @"%\marginparwidth = 15pt" + "\r\n"
                + @"\oddsidemargin = 0pt" + "\r\n"
                + @"\pagestyle{empty}" + "\r\n"
                + @"\begin{document}" + "\r\n"
                + @"\begin{center}{\LARGE $F^3-" + number + @" Solutions$}\end{center}" + "\r\n\r\n"
                + @"%insert the probs after each \item" + "\r\n"
                + @"\begin{enumerate}" + "\r\n\r\n");

            foreach (var finalizedProblem in finalizedProblemList)
                build.Append(@"\item " + finalizedProblem.solutionText + "\r\n\r\n");

            build.Append(@"\end{enumerate}" + "\r\n"
                + @"\end{document}");

            return build.ToString();
        }

        public void SetAtIndex(int i, Problem problem, FinalizedProblem finalizedProblem) 
        {
            if (i >= 0 && i < Count)
            {
                problemList[i] = problem;
                finalizedProblemList[i] = finalizedProblem;
                problemNameList[i] = problem.problemName;
            }
        }

        public void Add(Problem problem, FinalizedProblem finalizedProblem)
        {
            problemList.Add(problem);
            finalizedProblemList.Add(finalizedProblem);
            problemNameList.Add(problem.problemName);
            Count++;
        }

        public void DeleteAtIndex(int i) 
        {
            problemList.RemoveAt(i);
            finalizedProblemList.RemoveAt(i);
            problemNameList.RemoveAt(i);
            Count--;
        }
    }

    public class FinalizedProblem 
    {
        public string problemText, solutionText;
        public int solutionIndex;

        public FinalizedProblem(string problemText, string solutionText, int solutionIndex) 
        {
            this.problemText = problemText;
            this.solutionText = solutionText;
            this.solutionIndex = solutionIndex;
        }
    }
}
